import zc.buildout
import pkg_resources
import os
from os.path import join
import logging


logger = logging.getLogger('ely.maildrophostmonster')

config_template = """
MAILDROP_HOME="%(maildrop_dir)s"

# You can override the spool directory with this directive
# Without it, it'll be the "spool" subdirectory of $MAILDROP_HOME
# You can have one maildrop daemon monitor more than one spool folder
# by using a semicolon-separated value.
MAILDROP_SPOOL="%(maildrop_spool_dir)s"

# You can override the var directory with this directive
# Without it, it'll be the "var" subdirectory of $MAILDROP_HOME
MAILDROP_VAR="%(maildrop_dir)s"

# You can override the pid file with this directive
# Without it, it'll be the "maildrop.pid" file of $MAILDROP_VAR
MAILDROP_PID_FILE="%(maildrop_pid_file)s"

# You can override the log file with this directive
# Without it, it'll be the "maildrop.log" file of $MAILDROP_VAR
MAILDROP_LOG_FILE="%(maildrop_log_file)s"

# The SMTP server to be used for sending out email (e.g. smtp-relay.domain.com)
SMTP_HOST="%(smtp_host)s"

# The SMTP server port used for sending out email
SMTP_PORT=%(smtp_port)s

# How long to wait between spool checks
MAILDROP_INTERVAL=%(maildrop_interval)s

# Set debug mode. This will PREVENT the daemon from detaching from
# the controlling terminal. Under Windows the daemon will never detach
# from the terminal, regardless of this setting, because Windows does not
# support the method of detaching used.
DEBUG=%(debug)s

# Debug Receiver is used for specific debug/testing situations where emails
# are created normally, but the envelope receiver is set to the value of
# DEBUG_RECEIVER so email ends up in one mailbox but looks exactly like the
# actual receiver would see it. Use for debugging purposes only. The value
# is a string containing one or more comma-separated addresses.
DEBUG_RECEIVER="%(debug_receiver)s"

# Batch size for smtp-connection
# = 0 means bulk all mails at once
# > 0 means close/reopen connection after BATCH mails
MAILDROP_BATCH=%(maildrop_batch)s

# TLS usage. The values available are...
#   0 : Don't try to us TLS
#   1 : Try to use TLS if possible, but don't fail if TLS is not available
#   2 : Force TLS and fail if TLS is not available
# If a username/password is specified for the SMTP server, it is recommended
# to set the value to "2" to prevent password sniffing.
MAILDROP_TLS=%(maildrop_tls)s

# SMTP Authentication
# If the login and password are provided, authentication is attempted.
# If the authentication attempt fails, mail processing stops. Beware.
MAILDROP_LOGIN="%(maildrop_login)s"
MAILDROP_PASSWORD="%(maildrop_password)s"

# Wait between sending two mails, to avoid overloading the mail server
# This should be a float, in seconds
WAIT_INTERVAL=%(wait_interval)s

# Message ID
# If this is set to 1, the maildrop daaemon will add a RFC 2822-compliant 
# Message-Id header to the generated email message. Some spam-scanners will 
# reject mail without this header.
ADD_MESSAGEID=%(add_messageid)s

# Determine if the mail host object should be created with testing
# mode on or off. Typically this would be enabled on development hosts.
TESTING_MODE_DEFAULT=%(testing_mode_default)s

# Set daemon supervision mode. This will prevent the daemon from
# detaching from the controlling terminal which is what you want if
# you using something like daemontools to supervise the daemon.
SUPERVISED_DAEMON=%(supervised_daemon)s

"""

daemon_template = """#!/usr/bin/env sh
PYTHON="%(python)s"
MAILDROP="%(maildrophost)s/Products/MaildropHost/maildrop/maildrop.py"
CONFIG="%(config)s"
exec "$PYTHON" "$MAILDROP" "$CONFIG"
"""


class Recipe(object):

    def __init__(self, buildout, name, options):
        self.buildout, self.options, self.name = buildout, options, name
        options['location'] = join(
            buildout['buildout']['parts-directory'],
            self.name,
            )

    def get_bool(self, key, false='0', truth='1'):
        value = self.options.get(key, 'off')
        if value == 'off':
            return false
        elif value == 'on':
            return truth
        else:
            raise ValueError("Unknown value '%s' for key '%s'" % (value, key))

    def install(self):
        options = self.options
        location = options['location']

        # Create the maildrop spool.
        base_dir = self.buildout['buildout']['directory']
        maildrop_dir = join(base_dir, 'var', 'maildrop')
        if not os.path.exists(maildrop_dir):
            os.makedirs(maildrop_dir)

        # Create the logging directory.
        logging_dir = join(base_dir, 'var', 'log')
        if not os.path.exists(logging_dir):
            os.makedirs(logging_dir)

        # Setup the configuration.
        if not os.path.exists(location):
            os.makedirs(location)
        config = config_template % dict(
            maildrop_dir=maildrop_dir,
            maildrop_spool_dir=join(maildrop_dir, 'spool'),
            maildrop_pid_file=join(maildrop_dir, 'maildrop.pid'),
            maildrop_log_file=join(logging_dir, 'maildrop.log'),
            smtp_host=self.options.get('smtp-host', 'localhost'),
            smtp_port=self.options.get('smtp-port', '25'),
            maildrop_interval=self.options.get('maildrop-interval', '120'),
            debug=self.get_bool('debug'),
            debug_receiver=self.options.get('debug-receiver', ''),
            maildrop_batch=self.options.get('maildrop-batch', '0'),
            maildrop_tls=self.get_bool('maildrop-tls', '0', '2'),
            maildrop_login=self.options.get('maildrop-login', ''),
            maildrop_password=self.options.get('maildrop-password', ''),
            wait_interval=self.options.get('wait-interval', '0.0'),
            add_messageid=self.get_bool('add-messageid'),
            testing_mode_default=self.get_bool('testing-mode-default'),
            supervised_daemon=self.get_bool('supervised-daemon'),
            )
        config_path = join(location, 'config')
        open(config_path, 'w').write(config)

        # Install the daemon script.
        daemon_script = daemon_template % dict(
            python=self.buildout['buildout']['executable'],
            maildrophost=self.maildrophost_path(),
            config=config_path,
            )
        daemon_path = join(self.buildout['buildout']['bin-directory'],
                           'maildrop')
        open(daemon_path, 'w').write(daemon_script)
        os.chmod(daemon_path, 0755)
        logger.info("Generated script %r.", daemon_path)

        # Finish up.
        return [location, daemon_path]


    def maildrophost_path(self):
        return pkg_resources.working_set.find(
            pkg_resources.Requirement.parse('Products.MaildropHost')).location
